/**
 * Create in 2012-9-6 下午5:23:13.
 */
package kit4j.util.lang;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 此类包含用来操作数组（比如判断是否包含指定对象）的各种方法。
 * 
 * @author MiniKnife
 * 
 */
public abstract class ArrayUtil {

	/**
	 * 判断指定的对象数组中是否存在给定的对象。
	 * 
	 * @param a
	 *            对象数组
	 * @param key
	 *            要判断是否存在的对象
	 * @return 如果给定的对象数组不为null且包含给定的对象，则返回true，否则返回false。
	 */
	public static boolean contains(Object[] a, Object key) {
		if (key == null) {
			return hasNull(a);
		} else {
			if (a != null) {
				for (Object o : a) {
					if (key.equals(o)) {
						return true;
					}
				}
			}

			return false;
		}
	}

	/**
	 * 判断给定的对象数组中是否包含null值元素。
	 * 
	 * @param a
	 *            对象数组
	 * @return 如果给定的对象数组不为null且包含null值元素，则返回true，否则返回false。
	 */
	public static boolean hasNull(Object[] a) {
		if (a != null) {
			for (Object o : a) {
				if (o == null) {
					return true;
				}
			}
		}

		return false;
	}

	public static boolean isEmpty(Object[] a) {
		return a == null || a.length == 0;
	}

	public static boolean[] replace(boolean[] a, boolean[] b) {
		return replace(a, 0, a.length - 1, b, 0, b.length - 1);
	}

	public static boolean[] replace(boolean[] a, int fromIndex, int toIndex, boolean[] b) {
		return replace(a, fromIndex, toIndex, b, 0, b.length - 1);
	}

	public static boolean[] replace(boolean[] a, int fromIndexA, int toIndexA, boolean[] b, int fromIndexB, int toIndexB) {
		int length = Math.min(toIndexA - fromIndexA, toIndexB - fromIndexB) + 1;

		for (int i = 0; i < length; ++i) {
			a[i + fromIndexA] = b[i + fromIndexB];
		}

		return a;
	}

	public static byte[] replace(byte[] a, byte[] b) {
		return replace(a, 0, a.length - 1, b, 0, b.length - 1);
	}

	public static byte[] replace(byte[] a, int fromIndex, int toIndex, byte[] b) {
		return replace(a, fromIndex, toIndex, b, 0, b.length - 1);
	}

	public static byte[] replace(byte[] a, int fromIndexA, int toIndexA, byte[] b, int fromIndexB, int toIndexB) {
		int length = Math.min(toIndexA - fromIndexA, toIndexB - fromIndexB) + 1;

		for (int i = 0; i < length; ++i) {
			a[i + fromIndexA] = b[i + fromIndexB];
		}

		return a;
	}

	public static char[] replace(char[] a, char[] b) {
		return replace(a, 0, a.length - 1, b, 0, b.length - 1);
	}

	public static char[] replace(char[] a, int fromIndex, int toIndex, char[] b) {
		return replace(a, fromIndex, toIndex, b, 0, b.length - 1);
	}

	public static char[] replace(char[] a, int fromIndexA, int toIndexA, char[] b, int fromIndexB, int toIndexB) {
		int length = Math.min(toIndexA - fromIndexA, toIndexB - fromIndexB) + 1;

		for (int i = 0; i < length; ++i) {
			a[i + fromIndexA] = b[i + fromIndexB];
		}

		return a;
	}

	public static double[] replace(double[] a, double[] b) {
		return replace(a, 0, a.length - 1, b, 0, b.length - 1);
	}

	public static double[] replace(double[] a, int fromIndex, int toIndex, double[] b) {
		return replace(a, fromIndex, toIndex, b, 0, b.length - 1);
	}

	public static double[] replace(double[] a, int fromIndexA, int toIndexA, double[] b, int fromIndexB, int toIndexB) {
		int length = Math.min(toIndexA - fromIndexA, toIndexB - fromIndexB) + 1;

		for (int i = 0; i < length; ++i) {
			a[i + fromIndexA] = b[i + fromIndexB];
		}

		return a;
	}

	public static float[] replace(float[] a, float[] b) {
		return replace(a, 0, a.length - 1, b, 0, b.length - 1);
	}

	public static float[] replace(float[] a, int fromIndex, int toIndex, float[] b) {
		return replace(a, fromIndex, toIndex, b, 0, b.length - 1);
	}

	public static float[] replace(float[] a, int fromIndexA, int toIndexA, float[] b, int fromIndexB, int toIndexB) {
		int length = Math.min(toIndexA - fromIndexA, toIndexB - fromIndexB) + 1;

		for (int i = 0; i < length; ++i) {
			a[i + fromIndexA] = b[i + fromIndexB];
		}

		return a;
	}

	public static int[] replace(int[] a, int[] b) {
		return replace(a, 0, a.length - 1, b, 0, b.length - 1);
	}

	public static int[] replace(int[] a, int fromIndex, int toIndex, int[] b) {
		return replace(a, fromIndex, toIndex, b, 0, b.length - 1);
	}

	public static int[] replace(int[] a, int fromIndexA, int toIndexA, int[] b, int fromIndexB, int toIndexB) {
		int length = Math.min(toIndexA - fromIndexA, toIndexB - fromIndexB) + 1;

		for (int i = 0; i < length; ++i) {
			a[i + fromIndexA] = b[i + fromIndexB];
		}

		return a;
	}

	public static long[] replace(long[] a, long[] b) {
		return replace(a, 0, a.length - 1, b, 0, b.length - 1);
	}

	public static long[] replace(long[] a, int fromIndex, int toIndex, long[] b) {
		return replace(a, fromIndex, toIndex, b, 0, b.length - 1);
	}

	public static long[] replace(long[] a, int fromIndexA, int toIndexA, long[] b, int fromIndexB, int toIndexB) {
		int length = Math.min(toIndexA - fromIndexA, toIndexB - fromIndexB) + 1;

		for (int i = 0; i < length; ++i) {
			a[i + fromIndexA] = b[i + fromIndexB];
		}

		return a;
	}

	public static short[] replace(short[] a, short[] b) {
		return replace(a, 0, a.length - 1, b, 0, b.length - 1);
	}

	public static short[] replace(short[] a, int fromIndex, int toIndex, short[] b) {
		return replace(a, fromIndex, toIndex, b, 0, b.length - 1);
	}

	public static short[] replace(short[] a, int fromIndexA, int toIndexA, short[] b, int fromIndexB, int toIndexB) {
		int length = Math.min(toIndexA - fromIndexA, toIndexB - fromIndexB) + 1;

		for (int i = 0; i < length; ++i) {
			a[i + fromIndexA] = b[i + fromIndexB];
		}

		return a;
	}

	public static <T> T[] replace(T[] a, T[] b) {
		return replace(a, 0, a.length - 1, b, 0, b.length - 1);
	}

	public static <T> T[] replace(T[] a, int fromIndex, int toIndex, T[] b) {
		return replace(a, fromIndex, toIndex, b, 0, b.length - 1);
	}

	public static <T> T[] replace(T[] a, int fromIndexA, int toIndexA, T[] b, int fromIndexB, int toIndexB) {
		int length = Math.min(toIndexA - fromIndexA, toIndexB - fromIndexB) + 1;

		for (int i = 0; i < length; ++i) {
			a[i + fromIndexA] = b[i + fromIndexB];
		}

		return a;
	}

	public static boolean[] append(boolean[] a, boolean[] b) {
		return append(a, b, 0, b.length - 1);
	}

	public static boolean[] append(boolean[] a, boolean[] b, int from, int to) {
		boolean[] c = Arrays.copyOf(a, a.length + (to - from + 1));

		return replace(c, a.length, c.length - 1, b, from, to);
	}

	public static byte[] append(byte[] a, byte[] b) {
		return append(a, b, 0, b.length - 1);
	}

	public static byte[] append(byte[] a, byte[] b, int from, int to) {
		byte[] c = Arrays.copyOf(a, a.length + (to - from + 1));

		return replace(c, a.length, c.length - 1, b, from, to);
	}

	public static char[] append(char[] a, char[] b) {
		return append(a, b, 0, b.length - 1);
	}

	public static char[] append(char[] a, char[] b, int from, int to) {
		char[] c = Arrays.copyOf(a, a.length + (to - from + 1));

		return replace(c, a.length, c.length - 1, b, from, to);
	}

	public static double[] append(double[] a, double[] b) {
		return append(a, b, 0, b.length - 1);
	}

	public static double[] append(double[] a, double[] b, int from, int to) {
		double[] c = Arrays.copyOf(a, a.length + (to - from + 1));

		return replace(c, a.length, c.length - 1, b, from, to);
	}

	public static float[] append(float[] a, float[] b) {
		return append(a, b, 0, b.length - 1);
	}

	public static float[] append(float[] a, float[] b, int from, int to) {
		float[] c = Arrays.copyOf(a, a.length + (to - from + 1));

		return replace(c, a.length, c.length - 1, b, from, to);
	}

	public static int[] append(int[] a, int[] b) {
		return append(a, b, 0, b.length - 1);
	}

	public static int[] append(int[] a, int[] b, int from, int to) {
		int[] c = Arrays.copyOf(a, a.length + (to - from + 1));

		return replace(c, a.length, c.length - 1, b, from, to);
	}

	public static long[] append(long[] a, long[] b) {
		return append(a, b, 0, b.length - 1);
	}

	public static long[] append(long[] a, long[] b, int from, int to) {
		long[] c = Arrays.copyOf(a, a.length + (to - from + 1));

		return replace(c, a.length, c.length - 1, b, from, to);
	}

	public static short[] append(short[] a, short[] b) {
		return append(a, b, 0, b.length - 1);
	}

	public static short[] append(short[] a, short[] b, int from, int to) {
		short[] c = Arrays.copyOf(a, a.length + (to - from + 1));

		return replace(c, a.length, c.length - 1, b, from, to);
	}

	public static <T> T[] append(T[] a, T[] b) {
		return append(a, b, 0, b.length - 1);
	}

	public static <T> T[] append(T[] a, T[] b, int from, int to) {
		T[] c = Arrays.copyOf(a, a.length + (to - from + 1));

		return replace(c, a.length, c.length - 1, b, from, to);
	}

	public static <T> T[] eraseNull(T[] a) {
		return eraseNull(a, 0, a.length - 1);
	}

	public static <T> T[] eraseNull(T[] a, int from, int to) {
		List<T> list = new ArrayList<T>();

		for (int i = 0; i < a.length; ++i) {
			if (a[i] != null) {
				list.add(a[i]);
			}
		}

		return list.toArray(Arrays.copyOf(a, 0));
	}

	/**
	 * 合并字符串数组。合并后的数组的每个元素是原有数组中<code>clauseSize</code>指定的数量的元素的结合，其中每个元素使用
	 * <code>elementSeparator</code>进行分隔。
	 * 
	 * @param strArray
	 *            要合并的字符串数组
	 * @param clauseSize
	 *            合并后的数组中每个元素包含的原有数组中元素的数量
	 * @param elementSeparator
	 *            元素分隔符
	 * @return 合并后的数组。
	 * @throws NullPointerException
	 *             如果<code>strArray</code>或<code>elementSeparator</code>为null。
	 */
	public static String[] mergeStringArray(String[] strArray, int clauseSize, String elementSeparator) {
		int arrayLen = strArray.length;
		String[] newArray = new String[(arrayLen + clauseSize - 1) / clauseSize];

		for (int i = 0, j = -1; i < arrayLen; ++i) {
			if (i % clauseSize == 0) {
				++j;
				newArray[j] = strArray[i];
			} else {
				newArray[j] += elementSeparator + strArray[i];
			}
		}

		return newArray;
	}

}
